﻿using Script.Structs.Pawn;
using System.Collections.Generic;
using System.Linq;
using Game;
using Script.Game;
using UnityEngine;

/// <summary>
/// 创建关卡所需数据
/// </summary>
public struct CreateLevelInfo
{
    /// <summary>
    /// 地图数据
    /// </summary>
    public LevelInfoModel Model;

    public CreateLevelInfo(LevelInfoModel levelInfoModel)
    {
        Model = levelInfoModel;
    }
}

/// <summary>
/// 创建关卡棋子所需信息 敌人或者盟友
/// </summary>
public struct LevelPawnInfo
{
    /// <summary>
    /// 基础模板id
    /// </summary>
    public string PawnId;
    /// <summary>
    /// 所属阵营id
    /// </summary>
    public string CampId;
    /// <summary>
    /// 初始位置
    /// </summary>
    public int[] Pos;
    /// <summary>
    /// 关卡强化系数
    /// </summary>
    public float Intensify;

    /// <summary>
    /// 构造一个关卡棋子所需信息
    /// </summary>
    /// <param name="pawnId">基础模板id</param>
    /// <param name="campId">所属阵营id</param>
    /// <param name="pos">初始位置</param>
    /// <param name="intensify">关卡强化系数</param>
    public LevelPawnInfo(string pawnId, string campId, int[] pos, float intensify = 1)
    {
        PawnId = pawnId;
        CampId = campId;
        Pos = pos;
        Intensify = intensify;
    }
}

/// <summary>
/// 关卡数据策划的填表数据
/// </summary>
public struct LevelInfoModel
{
    /// <summary>
    /// 关卡id
    /// </summary>
    public string ID;

    /// <summary>
    /// 关卡名
    /// </summary>
    public string Name;

    /// <summary>
    /// 地图id
    /// </summary>
    public string MapId;

    /// <summary>
    /// 添加的剧本列表
    /// </summary>
    public AddScreenplayInfo[] AddScreenplayList;
    
    /// <summary>
    /// 棋子对象列表
    /// </summary>
    public LevelPawnInfo[] PawnInfoList;
    
    /// <summary>
    /// 玩家可选择出生位置
    /// </summary>
    public int[,] PlayerSelectPosList;

    public LevelInfoModel(string id, string name, string mapId, AddScreenplayInfo[] addScreenplayList, LevelPawnInfo[] pawnInfoList, int[,] playerSelectPosList)
    {
        ID = id;
        Name = name;
        MapId = mapId;
        AddScreenplayList = addScreenplayList;
        PawnInfoList = pawnInfoList;
        PlayerSelectPosList = playerSelectPosList;
    }
}

/// <summary>
/// 关卡数据
/// </summary>
public struct LevelInfo
{
   /// <summary>
   /// 回合数
   /// </summary>
   public int RoundsNum;

   /// <summary>
   /// 当前行动阵营
   /// </summary>
   public int CurActionCamp;

   /// <summary>
   /// 地图数据
   /// </summary>
   public MapInfo MapInfo;

   /// <summary>
   /// 所有阵营信息
   /// </summary>
   public CampInfoObj CampInfoObj;
   
   /// <summary>
   /// 当前回合状态
   /// </summary>
   public RoundState RoundState;

    public LevelInfo(MapInfo mapInfo,CampInfoObj campInfoObj,int roundsNum = 0,int curActionCamp = 0,RoundState roundState = RoundState.Start)
   {
        RoundsNum = roundsNum;
        CurActionCamp = curActionCamp;
        MapInfo = mapInfo;
        CampInfoObj = campInfoObj;
        RoundState = roundState;
   }
    
    public static LevelInfo zero = new LevelInfo(null,null);
    
    public void Zero()
    {
        RoundsNum = 0;
        CurActionCamp = 0;
        MapInfo = null;
        CampInfoObj = null;
        RoundState = RoundState.Start;
    }
}

/// <summary>
/// 关卡数据实列
/// </summary>
public class LevelInfoObj
{
    /// <summary>
    /// 回合数
    /// </summary>
    public int RoundsNum;
    /// <summary>
    /// 当前行动阵营
    /// </summary>
    public string CurActionCamp;
    /// <summary>
    /// 初始行动阵营
    /// </summary>
    public string DefineActionCamp;
    /// <summary>
    /// 地图数据
    /// </summary>
    public MapInfo MapInfo;
    /// <summary>
    /// 所有阵营信息
    /// </summary>
    public CampInfoObj CampInfoObj;
    /// <summary>
    /// 阵营和棋子对象表
    /// </summary>
    public Dictionary<string,List<GameObject>> CampPawnDict;
    /// <summary>
    /// 剧本列表
    /// </summary>
    public List<ScreenplayObj> ScreenplayObjs;
    /// <summary>
    /// 当前回合状态
    /// </summary>
    public RoundState RoundState;
    /// <summary>
    /// 关卡结束
    /// </summary>
    public bool LevelOver;
    /// <summary>
    /// 胜利标志
    /// </summary>
    public bool WinFlag;

    public LevelInfoObj(MapInfo mapInfo,CampInfoObj campInfoObj)
    {
        MapInfo = mapInfo;
        CampInfoObj = campInfoObj;
        
        RoundsNum = 0;
        DefineActionCamp = "";
        CurActionCamp = "";
        CampPawnDict = new Dictionary<string, List<GameObject>>();
        ScreenplayObjs = new List<ScreenplayObj>();
        RoundState = RoundState.Wait;
        LevelOver = false;
        WinFlag = false;
    }
    
    public static LevelInfoObj Zero = new LevelInfoObj(null,null);
    
    /// <summary>
    /// 初始化关卡对象
    /// </summary>
    public void Init()
    {
        RoundsNum = 0;
        DefineActionCamp = "";
        CurActionCamp = "";
        MapInfo = null;
        CampInfoObj = null;
        CampPawnDict.Clear();
        ScreenplayObjs.Clear();
        RoundState = RoundState.Wait;
        LevelOver = false;
        WinFlag = false;
    }
    
    /// <summary>
    /// 获取当前阵营信息
    /// </summary>
    public CampInfoModel GetCurCampInfo()
    {
        return this.CampInfoObj.Dict[this.CurActionCamp];
    }
    
    /// <summary>
    /// 判断当前阵营是否是ai控制
    /// </summary>
    public bool IsAIControl()
    {
        return CampInfoObj.isAIControl(CurActionCamp);
    }
    
    /// <summary>
    /// 获取某个点周围的满足指定权值列表的点
    /// </summary>
    /// <param name="pos">目标位置</param>
    /// <param name="movementList">权值列表</param>
    /// <returns></returns>
    public List<Vector2Int> GetPosRangeList(Vector2Int pos,int[] movementList,CheckBoundary checkBoundary)
    {

        return AStart.GetRangeListByWeightCustom(new CheckRangeInfo(
            MapInfo,
            pos,
            movementList.Length,
            delegate(int[] sMap,List<int> mapList, ref List<int> outMapList)
            {
                for (int i = 0; i < movementList.Length; i++)
                {
                    //如果这个范围是不包含的
                    if (movementList[i] != 1) continue;
                    foreach (var v in mapList)
                    {
                        if (sMap[v] == i+1)
                        {
                            outMapList.Add(v); 
                        } 
                    }
                }
            },
            checkBoundary
        ));
    }
    
    /// <summary>
    /// 获取某个点周围的满足权值条件的点
    /// </summary>
    /// <param name="pos">目标位置</param>
    /// <param name="movement">权值</param>
    /// <param name="isAll">是否是全部</param>
    /// <returns></returns>
    public List<Vector2Int> GetPosRangeList(Vector2Int pos,int movement,CheckBoundary checkBoundary)
    {
        return AStart.GetRangeListByWeightCustom(new CheckRangeInfo(
            MapInfo,
            pos,
            movement,
            null, 
            checkBoundary
        ));
    }
    
    /// <summary>
    /// 获取一个棋子在某个位置的可行动区域
    /// </summary>
    /// <param name="pos"></param>
    /// <param name="pawn"></param>
    /// <returns></returns>
    public List<Vector2Int> GetPawnMoveList(Vector2Int pos,PawnState movePawnState,bool addAttackRange = false)
    {
        // 移动方法的边界检查
        CheckBoundary checkBoundary = delegate(Vector2Int i)
        {
            if (!MapInfo.CheckGridInPosition(i))
            {
                return false;
            }

            var pawn = GetPawnByPos(i);
            if (pawn != null && !CheckCanOperate(CampPowerType.Span, movePawnState,pawn.GetComponent<PawnState>()))
            {
                return false;
            }

            return true;
        };
        if (addAttackRange)
        {
            List<int> RangeList = new List<int>();
            for (int i = 0; i < movePawnState.baseProp.Action; i++)
            {
                RangeList.Add(1);
            }

            foreach (var v in movePawnState.GetAttackRange())
            {
                RangeList.Add(v);
            }
            return GetPosRangeList(pos,RangeList.ToArray(),checkBoundary); 
        }
        return GetPosRangeList(pos, movePawnState.baseProp.Action,checkBoundary);
    }
    
    /// <summary>
    /// 获取这个坐标的棋子 死亡的棋子无法获取
    /// </summary>
    /// <param name="MapInfo"></param>
    /// <param name="pos"></param>
    /// <returns></returns>
    public GameObject GetPawnByPos(Vector2Int pos)
    {
        if (!MapInfo.CheckGridInPosition(pos) || !GameState.Pos2PawnDict.ContainsKey(pos) || GameState.Pos2PawnDict[pos].GetComponent<PawnState>().dead)
        {
            return null;
        }
        return GameState.Pos2PawnDict[pos];
    }
    
    /// <summary>
    /// 获取一个棋子在某个位置的可攻击区域
    /// </summary>
    /// <param name="pos"></param>
    /// <param name="Pawn"></param>
    /// <returns></returns>
    public List<Vector2Int> GetPawnAttackList(Vector2Int pos,PawnState pawn)
    {
        return GetPosRangeList(pos,pawn.GetAttackRange(),delegate(Vector2Int i)
        {
            if (!MapInfo.CheckGridInPosition(i))
            {
                return false;
            }
            return true;
        });
    }
    
    /// <summary>
    /// 获取一个棋子的可行动攻击区域
    /// </summary>
    /// <param name="pos"></param>
    /// <param name="pawn"></param>
    /// <returns></returns>
    public List<Vector2Int> GetPawnMoveAttackList(List<Vector2Int> posList,PawnState pawn)
    {
        HashSet<Vector2Int> tempPosHashSet = new HashSet<Vector2Int>();
        foreach (var pos in posList)
        {
            foreach (var attackPos in GetPawnAttackList(pos, pawn))
            {
                tempPosHashSet.Add(attackPos);
            }
        }
        return tempPosHashSet.ToList(); 
    }
    
    /// <summary>
    /// 棋子移动到某个位置
    /// </summary>
    public bool MovePawn(Vector2Int pos,GameObject pawn)
    {
        // 原地移动直接成功
        if (GameState.Pos2PawnDict.ContainsKey(pos) && GetPawnByPos(pos).Equals(pawn))
        {
            return true;
        }
        // 如果要移动的棋子是存在的,且移动坐标没有棋子
        if (GameState.Pawn2PosDict.ContainsKey(pawn) && !GameState.Pos2PawnDict.ContainsKey(pos))
        {
            //逻辑位置处理
            SceneVariants.GetLevelManager().ClearPawn(pawn);
            SceneVariants.GetLevelManager().AddPawn(pos,pawn);
            
            //显示位置处理 这里可以加入时间轴控制，让棋子产生移动效果
            pawn.GetComponent<PawnState>()
                .SetPawnPos(SceneVariants.levelManager.GetPosByGridPos(pos));
            SceneVariants.NotifyMessageEvent(EventEnum.UpdatePawnState,pawn);
            return true;
        }

        return false;
    }
    
    /// <summary>
    /// 检查棋子A是否可以对这个棋子B进行某些操作
    /// </summary>
    /// <param name="campPowerType"></param>
    /// <param name="pawnA"></param>
    /// <param name="pawnB"></param>
    /// <returns></returns>
    public static bool CheckCanOperate(CampPowerType campPowerType,PawnState pawnAState,PawnState pawnBState)
    {
        //当前阵营的可攻击列表里是否存在这个阵营
        if (pawnAState.Equals(null) || pawnBState.Equals(null) || 
            !CampInfoObj.CheckCompsPower(pawnAState.CampId,pawnBState.CampId,campPowerType))
        {
            return false;
        }

        return true;
    }
    
    //获取这个坐标的地图块
    public static GameObject GetMapByPos(Vector2Int pos)
    {
        return GameState.MapGameObjects[pos.x,pos.y];
    }
}

///<summary>
///回合状态
///</summary>
public enum RoundState{
   Start,   //开始回合
   Over,  //结束回合
   Wait,   //等待
   PawnAction, // 棋子行动
}

/// <summary>
/// 行动所需信息
/// </summary>
public struct ActionInfo
{
    /// <summary>
    /// 当前选中位置
    /// </summary>
    public Vector2Int TargetPos;

    /// <summary>
    /// 当前选中对象
    /// </summary>
    public GameObject Pawn;
    
    /// <summary>
    /// 关卡实例对象
    /// </summary>
    public LevelInfoObj LevelInfoObj;
    
    public ActionInfo(Vector2Int targetPos, GameObject pawn, LevelInfoObj levelInfoObj)
    {
        this.TargetPos = targetPos;
        Pawn = pawn;
        LevelInfoObj = levelInfoObj;
    }
}

public delegate void ActionDelegation(ActionInfo actionInfo);